#include "conf_parser.hh"

ConfParser::ConfParser (ObjVect* map):
  map_ (map)
{
  list_ = 0;

  std::ifstream file;

  file.open ("content/parsing_rules.r");

  // si le fichier de rules n'existe pas
  if (!file.is_open ())
  {
    std::cerr << "No parsing rules file." << std::endl
      << "Please create it in: content/parsing_rules.r" << std::endl;
    return;
  }

  std::string name;
  std::string id;

  Rule* r = 0;

  List<Rule*>* tmp = 0;

  std::cout << std::endl
	    << "***** Building rules *****" << std::endl
	    << std::endl;

  file >> name;
  file >> id;
  while (!file.eof ())
  {
    // on la cree et on l'ajoute
    r = new Rule (name, id);

    tmp = new List<Rule*>;

    tmp->next = list_;
    tmp->elt = r;

    list_ = tmp;
    std::cout << "Rule:'** " << name << " " << id << " ** added correctly." << std::endl;
    // on recupere les infos de la regle
    file >> name;
    file >> id;
  }

  std::cout << std::endl
	    << "***** End building rules *****" << std::endl
	    << std::endl;
  file.close ();
}

ConfParser::~ConfParser ()
{
  List<Rule*>* tmp = list_;
  List<Rule*>* pred = list_;

  while (tmp != 0)
    {
      pred = tmp;
      tmp = tmp->next;

      delete pred->elt;
      delete pred;
    }
}

void
ConfParser::parse (std::string filename, GameManager* gm)
{
  if (!list_)
    return;

  std::ifstream file;

  file.open (filename.c_str ());

  // si le fichier n'existe pas
  if (!file.is_open ())
    {
      std::cerr << "File " << filename << " doesn't exist or cannot be open."
		<< std::endl;
      return;
    }

  std::string str;
  List<Rule*>* tmp = list_;
  Vector3f pos;
  Vector3f size;
  std::string obj_type;
  int obj_type_id;

  float d1 = 0;
  float d2 = 0;
  float d3 = 0;
  float d4 = 0;
  float d5 = 0;
  float d6 = 0;

  int player_id = 0;

  Object* res = 0;

  OctreeRts* oct = 0;

  int player_nb = 0;

  std::cout << "***** Initializing map *****" << std::endl
	    << std::endl;

  file >> str;
  if (str != "flat")
    {
      std::cerr << "Other map types than flat are not handled yet." << std::endl;
      assert (false);
    }
  else
    {
      int value = 0;

      file >> value;
      std::cout << "The map size will be " << value << " on " << value << "." << std::endl << std::endl;

      oct = OctreeRts::Instance (value);
      Map* map = new Map (value, value);

      oct->insert_map (map);
      delete map;

    }
  std::cout << "***** Map Initialization done *****" << std::endl << std::endl;

  std::cout << "***** Initializing Players *****" << std::endl << std::endl;
  file >> player_nb;
  std::vector<Player*> p_list;
  Player* play = 0;
  for (int i = 0; i < player_nb; ++i)
    {
      play = new Player ();
      p_list.push_back (play);
      gm->add_player (play);
    }
  std::cout << "***** Players Initialization Done *****" << std::endl << std::endl;

  std::cout << "***** Building Objects *****" << std::endl
	    << std::endl;

  file >> str;

  // on recupere la position de l'objet
  file >> d1;
  file >> d2;
  file >> d3;

  // on recupere la size de l'objet
  file >> d4;
  file >> d5;
  file >> d6;

  // on recupere le player id
  file >> player_id;

  // on recupere le type de l'objet
  file >> obj_type;

  while (str != "allo")
  {
    tmp = list_;
    // recherche de la rule qui correspond
    while (tmp->elt->name_get ().compare (str))
      tmp = tmp->next;
    pos.val_set (d1, d2, d3);
    size.val_set (d4, d5, d6);

    if (obj_type == "building" || obj_type == "unit")
      {
	file >> obj_type_id;
	std::cout << "It's a " << obj_type << " with the id: " << obj_type_id << std::endl;
      }
    // on cree l'objet et on l'ajoute dans l'octree
    res = tmp->elt->make (pos, size, player_id, obj_type, obj_type_id);
    if (tmp->elt->is_building ())
      p_list[player_id]->add_building (tmp->elt->building ());
    else
      {
	p_list[player_id]->add_unit (tmp->elt->unit ());
	gm->ai_handler ()->add_object (tmp->elt->unit ());
      }

    map_->add (res);
    oct->add_obj (res);
    std::cout << "Object: '" << str << "' built and added in the octree with:" << std::endl
	      << "x = " << d1 << ", y = " << d2 << ", z = " << d3 << " and" << std::endl
	      << "size_x = " << d4 << ", size_y = " << d5 << ", size_z = " << d6 << std::endl;

    str = "allo";
    file >> str;
    // on recupere la position de l'objet
    file >> d1;
    file >> d2;
    file >> d3;

    // on recupere la size de l'objet
    file >> d4;
    file >> d5;
    file >> d6;

    // on recupere le player id
    file >> player_id;

    // on recupere le type de l'objet
    file >> obj_type;
  }

  std::cout << std::endl
	    << "***** End building Objects *****" << std::endl
	    << std::endl;

  file.close ();
}
